﻿#pragma once
#include "DSP.h"
#include "RingBuffer.h"
#include "BufferDelayer.h"

namespace yzrilyzr_dsp{
	ECLASS(LowPassFeedbackCombFilter, public DSP){
	public:
	u_time_ms delayTimeMs=0;
	u_normal_01 roomSize=0;
	u_normal_01 damper=0;
	BufferDelayer::DelayFunction delayFunction=BufferDelayer::linearDelay;
	private:
	RingBufferSample buffer;
	u_sample delayIndex=0;
	u_sample filterValue=0;
	u_sample b0=0;
	u_sample a1=0;
	u_sample s_roomsize=0;
	public:
	LowPassFeedbackCombFilter();
	LowPassFeedbackCombFilter(u_time_ms delayTimeMs, u_normal_01 roomSize, u_normal_01 damper)
		:delayTimeMs(delayTimeMs), roomSize(roomSize), damper(damper){}
	u_sample procDsp(u_sample input) override{
		u_sample delayed=delayFunction(buffer, delayIndex);
		filterValue=b0 * delayed - a1 * filterValue;
		u_sample output=input + s_roomsize * filterValue;
		buffer.write(output);
		return output;
	}
	void init(u_sample_rate sampleRate) override{
		delayIndex=RingBufferUtil::ms2DelayIndex(delayTimeMs, sampleRate);
		buffer.ensureCapacity(delayIndex);
		b0=1.0 - damper;
		a1=-damper;
		s_roomsize=roomSize;
	}
	void resetMemory() override{
		buffer.fill(0);
	}
	std::shared_ptr<DSP> cloneDSP() override{
		return std::make_shared < LowPassFeedbackCombFilter>(delayTimeMs, roomSize, damper);
	}
	void cloneParam(DSP * obj1)override{
		if(auto other=dynamic_cast<LowPassFeedbackCombFilter *>(obj1)){
			delayTimeMs=other->delayTimeMs;
			roomSize=other->roomSize;
			damper=other->damper;
			delayFunction=other->delayFunction;
		}
	}
	yzrilyzr_lang::String toString()const override;
	};
}